package org.fhm.zdte.client.service.proxy;

import org.fhm.substrate.annotation.Component;
import org.fhm.substrate.annotation.Setup;
import org.fhm.substrate.service.LoggerHandler;
import org.fhm.substrate.standard.ILogger;
import org.fhm.zdte.client.api.ClientApi;
import org.fhm.zdte.client.exception.ClientException;
import org.fhm.zdte.client.pojo.ProxyRequestBody;
import org.fhm.zdte.client.service.ClientStarter;
import org.fhm.zdte.client.standard.IProxyRequestSender;
import org.fhm.zdte.common.ability.IGetIdentification;
import org.fhm.zdte.common.constant.DataTransform;
import org.fhm.zdte.common.constant.protocol.ContentType;
import org.fhm.zdte.common.pojo.Request;
import org.fhm.zdte.common.pojo.Result;
import org.fhm.zdte.common.pojo.ZDTEFile;
import org.fhm.zdte.common.standard.IJsonConvertor;

import java.util.Map;
import java.util.Objects;

import static org.fhm.zdte.client.pojo.ProxyRequestBody.*;


/**
 * The proxy request sender for {@link ContentType#TEXT}.
 *
 * @author 谭波
 * @since 2023/12/29
 */
@Component
public class CommonProxyRequestSender implements IProxyRequestSender {

    private static final ILogger logger = LoggerHandler.getLogger(CommonProxyRequestSender.class);

    @Setup
    private IJsonConvertor iJsonConvertor;

    @Setup
    private IGetIdentification iGetIdentification;

    @Setup
    private ClientApi clientApi;

    @Setup
    private ClientStarter clientStarter;

    @Override
    public String request(ProxyRequestBody body) {
        Result<?> result = Result.getFailMessage("target type not match");
        String targetType = body.getTargetType();
        String messageNumber = body.getMessageNumber();
        if (Objects.isNull(targetType))
            return iJsonConvertor.toJson(result);
        try {
            String interfaceUrl = body.getInterfaceUrl();
            switch (targetType) {
                case TO_SERVER:
                    logger.info("request a servlet with interface {} to the server side", interfaceUrl);
                    result = clientApi.requestServer(interfaceUrl, String.class, body.getParameters(), messageNumber);
                    break;
                case TO_MYSELF:
                    logger.info("request a servlet with interface {} to the local client side", interfaceUrl);
                    result = clientStarter.dispatchInternalServlet(new Request(interfaceUrl, body.getParameters()));
                    break;
                case TO_MYSELF_SERVICE:
                    logger.info("request a myself servlet with interface {} to the client side", interfaceUrl);
                    result = clientStarter.dispatchServlet(
                            iGetIdentification.getIdentification(),
                            new Request(interfaceUrl, body.getParameters())
                    );
                    break;
                case TO_CLIENT:
                    logger.info("request a servlet with interface {} to the client side", interfaceUrl);
                    result = clientApi.request(
                            body.getTarget(), interfaceUrl,
                            String.class, body.getParameters(), messageNumber,
                            ContentType.getContentType(body.getContentType())
                    );
                    break;
            }
        } catch (ClientException e) {
            result = Result.getFailMessage(e.getMessage());
        }
        result.setMessageNumber(messageNumber);
        return parseResult(result);
    }

    private String parseResult(Result<?> result) {
        if (result.getContentType().equals(ContentType.FILE)) {
            Map<String, Object> params = result.getParams();
            Object o = params.remove(DataTransform.FILE_KEY);
            if (o instanceof ZDTEFile) {
                ZDTEFile zdteFile = (ZDTEFile) o;
                return iJsonConvertor.toJson(result) + DataTransform.PROXY_PACKET_SEPARATOR + zdteFile.getFileData();
            }
            return iJsonConvertor.toJson(Result.getFailMessage("failed to parse file"));
        } else
            return iJsonConvertor.toJson(result);
    }

}
